﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;

namespace Shapes {

	internal class CodeWriter {

		List<string> code = new List<string>();
		public int indentLevel = 0;

		public void Append( string s ) {
			if( s.Contains( '\n' ) )
				Append( s.Split( '\n' ) );
			else
				code.Add( s == "" ? "" : new string( '\t', indentLevel ) + s );
		}

		public void Append( IEnumerable<string> lines ) {
			foreach( string s in lines )
				Append( s );
		}

		public void AppendHeader() {
			Append( ShapesInfo.FILE_HEADER_COMMENT_A );
			Append( ShapesInfo.FILE_HEADER_COMMENT_B );
		}

		public void Spacer() => Append( "" );

		public void Using( string s ) => Append( $"using {s};" );
		public void Comment( string s ) => Append( $"// {s}" );

		public CodeScope Scope( string s ) => new CodeScope( s, this );

		public MainScope MainScope( Type generatorType, params string[] usings ) => new MainScope( usings, generatorType.Name, this );

		public void WriteTo( string path ) {
			if( ShapesIO.TryMakeAssetsEditable( path ) ) {
				File.WriteAllLines( path, code );
				AssetDatabase.Refresh(); // reload scripts
			}
		}

		public override string ToString() => string.Join( "\n", code );

	}

	internal class MainScope : IDisposable {

		readonly CodeWriter writer;

		public MainScope( string[] usings, string generatorName, CodeWriter writer ) {
			this.writer = writer;
			usings.ForEach( writer.Using );
			writer.Spacer();
			writer.AppendHeader();
			writer.Comment( "this file is auto-generated by " + generatorName );
			writer.Append( $"namespace {nameof(Shapes)} {{" );
			writer.indentLevel++;
		}


		public void Dispose() {
			writer.Spacer();
			writer.indentLevel--;
			writer.Append( "}" );
		}
	}


	internal class CodeScope : IDisposable {

		readonly CodeWriter writer;

		public CodeScope( string s, CodeWriter writer ) {
			this.writer = writer;
			writer.Append( $"{s} {{" );
			writer.indentLevel++;
		}


		public void Dispose() {
			writer.indentLevel--;
			writer.Append( "}" );
		}
	}


}